import { ChangeDetectorRef, Component, HostListener, OnInit } from '@angular/core';
import { editor } from 'monaco-editor';
import { filter, first } from 'rxjs/operators';
import { PyodideService } from '../pyodide/pyodide.service';
import nightowl from "../course/NightOwl";
import { PythonExceptionMessage, PythonOutputMessage } from '../pyodide/PythonMessage';
// eslint-disable-next-line  @typescript-eslint/no-explicit-any
declare const monaco: any;

@Component({
  selector: 'app-workground',
  templateUrl: './workground.component.html',
  styleUrls: ['./workground.component.scss']
})
export class WorkgroundComponent implements OnInit {

  constructor(private pyodide: PyodideService, private window: Window, private cdr: ChangeDetectorRef) { }
  pyodideLoaded = false;
  ngOnInit(): void {
    this.pyodide.loadingState.asObservable().pipe(filter(x => x === 'loaded'), first()).subscribe(x => {
      this.pyodideLoaded = true;
    });
  }
  isRunModalVisible = false;
  code = '';
  inputText = '';
  output = '';
  editorLoaded = false;
  editor?: editor.IStandaloneCodeEditor;
  onEditorInit(e: editor.ICodeEditor | editor.IEditor): void { // 这里的转换不太行
    this.editor = e as editor.IStandaloneCodeEditor;
    this.editorLoaded = true;
    // 大概是触发条件
    const blockContext = "editorTextFocus && !suggestWidgetVisible && !renameInputVisible && !inSnippetMode " + "&& !quickFixWidgetVisible";
    this.editor.addAction({
      id: "execute",
      label: "运行和检查",
      keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
      contextMenuGroupId: "2_execution",
      precondition: blockContext,
      run: () => {
        this.run();
      }
    });
    monaco.editor.defineTheme('nightowl', nightowl);
    monaco.editor.setTheme('nightowl');
  }
  codeRunning = false;
  taskDonePrompt = '';
  runModalOutputStyle = "";
  async run() { // 在Python中能够访问
    this.isRunModalVisible = true;
    // 不检查有概率不能及时跳出来，可能是因为在多线程里面操作？
    this.cdr.detectChanges();
    let inputLines = this.inputText.split('\n');
    this.output = '';
    if (this.inputText === '') {
      inputLines = [];
    }
    (this.window as any).pyodide_input_lines = inputLines;
    // await this.pyodide.runAsync(this.code);
    this.codeRunning = true;
    const observer = await this.pyodide.simpleRun(this.code, inputLines);
    observer.subscribe(message => {
      if (message.type === 'output') {
        const msg = message as PythonOutputMessage;
        this.output += msg.text;
        this.runModalOutputStyle = "";
      } else if (message.type === "exception") {
        const msg = message as PythonExceptionMessage;
        this.output += msg.message;
        this.codeRunning = false;
        this.runModalOutputStyle = "exception";
      } else if (message.type === "finish") {
        this.codeRunning = false;
      }
      this.cdr.detectChanges();
    });
    this.modalOkExtra = () => { };
    this.cdr.detectChanges();
  }
  modalOkExtra = () => { };
  onRunModalOk() {
    this.modalOkExtra();
    this.closeRunModal();
  }
  modalCancelExtra = () => { }; onRunModalCancel() {
    this.modalCancelExtra();
    this.closeRunModal();
  }
  closeRunModal() {
    this.isRunModalVisible = false;
  }
  @HostListener("document:keydown", ["$event"]) handleKeyboardEvent(event: KeyboardEvent) { // console.log(event);
    const key = event.key;
    if (key === "Enter") {
      if (event.ctrlKey || event.metaKey) {
        if (!this.isRunModalVisible) {
          this.run();
        }
        return false;
      }else{
        this.isRunModalVisible = false;
      }
    }
    return true;
  }
}
